using System;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using AK.Wwise.TreeView;

namespace AudioStudio.Editor
{
	public abstract class AudioBaseTypeDrawer : PropertyDrawer
	{
        protected AkWwiseProjectData.WwiseObjectType m_objectType;
		protected string m_typeName;

		private static Rect s_pickerPos = new Rect();

		private static Rect s_pressedPosition = new Rect();
		private static bool s_buttonWasPressed = false;

		private static AkWwiseProjectData.WwiseObjectType s_objectType;
        private static SerializedProperty s_serializedProperty;

		public abstract void SetupSerializedProperties(SerializedProperty property);

		// taken and modified from AkUtilities.GetLastRectAbsolute()
		public static Rect GetLastRectAbsolute()
		{
			Type inspectorType = Assembly.GetAssembly(typeof(UnityEditor.Editor)).GetType("UnityEditor.InspectorWindow");

			FieldInfo currentInspectorFieldInfo = inspectorType.GetField("s_CurrentInspectorWindow", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
			PropertyInfo positionPropInfo = inspectorType.GetProperty("position", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

			Rect InspectorPosition = (Rect)positionPropInfo.GetValue(currentInspectorFieldInfo.GetValue(null), null);

			Rect absolutePos = new Rect(InspectorPosition.x, InspectorPosition.y, InspectorPosition.width, 0);
			return absolutePos;
		}

        private AkDragDropData GetAkDragDropData()
        {
            AkDragDropData DDData = DragAndDrop.GetGenericData(AkDragDropHelper.DragDropIdentifier) as AkDragDropData;
            return (DDData != null && DDData.typeName.Equals(m_typeName)) ? DDData : null;
        }

        private void HandleDragAndDrop(UnityEngine.Event currentEvent, Rect dropArea)
        {
            if (currentEvent.type == EventType.DragExited)
            {
                // clear dragged data
                DragAndDrop.PrepareStartDrag();
            }
            else if (currentEvent.type == EventType.DragUpdated || currentEvent.type == EventType.DragPerform)
            {
                if (dropArea.Contains(currentEvent.mousePosition))
                {
                    var DDData = GetAkDragDropData();

                    if (currentEvent.type == EventType.DragUpdated)
                    {
                        DragAndDrop.visualMode = DDData != null ? DragAndDropVisualMode.Link : DragAndDropVisualMode.Rejected;
                    }
                    else
                    {
                        DragAndDrop.AcceptDrag();

                        if (DDData != null)
                        {
                            OnDragAndDrop(s_serializedProperty, DDData);

                            //needed for the undo operation to work
                            GUIUtility.hotControl = 0;
                        }
                    }
                    currentEvent.Use();
                }
            }
        }

        protected virtual string GetText(SerializedProperty property)
        {
            SerializedProperty name = property.FindPropertyRelative("name");
            return name.stringValue;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
		{
			// Using BeginProperty / EndProperty on the parent property means that
			// prefab override logic works on the entire property.
			EditorGUI.BeginProperty(position, label, property);
            SetupSerializedProperties(property);

            // Draw label
            position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

			/************************************************Update Properties**************************************************/
            string componentName = GetText(property);

			/********************************************Draw GUI***************************************************************/
			var style = new GUIStyle(GUI.skin.button);
			style.alignment = TextAnchor.MiddleLeft;
			style.fontStyle = FontStyle.Normal;

			if (componentName.Equals(String.Empty))
			{
				componentName = "No " + m_typeName + " is currently selected";
				style.normal.textColor = Color.red;
			}

			if (GUI.Button(position, componentName, style))
			{
				s_pressedPosition = position;
				s_buttonWasPressed = true;

				// We don't want to set object as dirty only because we clicked the button.
				// It will be set as dirty if the wwise object has been changed by the tree view.
				GUI.changed = false;
			}

			var currentEvent = UnityEngine.Event.current;

			if (currentEvent.type == EventType.Repaint)
			{
				if (s_buttonWasPressed && s_pressedPosition.Equals(position))
				{
					s_pickerPos = GetLastRectAbsolute();
					s_objectType = m_objectType;
                    s_serializedProperty = property;

                    EditorApplication.delayCall += DelayCreateCall;
					s_buttonWasPressed = false;
				}
			}

			//HandleDragAndDrop(currentEvent, position);

			EditorGUI.EndProperty();
		}

		private void DelayCreateCall()
		{
			AkWwiseComponentPicker.Create(s_objectType, s_serializedProperty, s_pickerPos, OnPickerChanged);
		}

        protected virtual void OnPickerChanged(SerializedProperty property,TreeViewItem treeItem)
        {

        }

        protected virtual void OnDragAndDrop(SerializedProperty property, AkDragDropData data)
        {
            AudioUtility.SetByteArrayProperty(property.FindPropertyRelative("valueGuid.Array"), data.guid.ToByteArray());
            property.serializedObject.ApplyModifiedProperties();            
        }

        protected void OnDragAndDropGroup(SerializedProperty property, AkDragDropData data)
        {
            AkDragDropGroupData groupData = data as AkDragDropGroupData;
            if (groupData != null)
                AudioUtility.SetByteArrayProperty(property.FindPropertyRelative("groupGuid.Array"), groupData.groupGuid.ToByteArray());
            property.serializedObject.ApplyModifiedProperties();
        }

        protected void PickerChangeGroup(SerializedProperty property, TreeViewItem treeItem, List<AkWwiseProjectData.GroupValWorkUnit> list)
        {
            var guidProperty = property.FindPropertyRelative("valueGuid.Array");
            Guid guid = Guid.Empty;
            if (treeItem != null)
            {
                guid = new Guid((treeItem.DataContext as AkWwiseTreeView.AkTreeInfo).Guid);
            }
            Guid groupGuid = Guid.Empty;
            if (treeItem != null && treeItem.Parent != null)
            {
                groupGuid = new Guid((treeItem.Parent.DataContext as AkWwiseTreeView.AkTreeInfo).Guid);
            }
            AudioUtility.SetByteArrayProperty(guidProperty, guid.ToByteArray());
            for (int i = 0; i < list.Count; i++)
            {
                var group = list[i].List.Find(x => new Guid(x.Guid).Equals(groupGuid));

                if (group != null)
                {
                    int index = group.ValueGuids.FindIndex(x => new Guid(x.bytes).Equals(guid));

                    if (index < 0)
                        break;

                    property.FindPropertyRelative("groupID").intValue = group.ID;
                    property.FindPropertyRelative("ID").intValue = group.valueIDs[index];
                    property.FindPropertyRelative("groupName").stringValue = group.Name;
                    property.FindPropertyRelative("name").stringValue = group.values[index];
                    property.serializedObject.ApplyModifiedProperties();
                    return;
                }
            }

            property.FindPropertyRelative("groupID").intValue = 0;
            property.FindPropertyRelative("ID").intValue = 0;
            property.FindPropertyRelative("groupName").stringValue = string.Empty;
            property.FindPropertyRelative("name").stringValue = string.Empty;
            property.serializedObject.ApplyModifiedProperties();
        }
        
        protected void PickerChanged(SerializedProperty property, TreeViewItem treeItem, List<AkWwiseProjectData.AkInfoWorkUnit> list)
        {
            Guid guid = Guid.Empty;
            if (treeItem != null)
            {
                guid = new Guid((treeItem.DataContext as AkWwiseTreeView.AkTreeInfo).Guid);
            }

            var guidProperty = property.FindPropertyRelative("valueGuid.Array");
            AudioUtility.SetByteArrayProperty(guidProperty, guid.ToByteArray());
            for (int i = 0; i < list.Count; i++)
            {
                var element = list[i].List.Find(x => new Guid(x.Guid).Equals(guid));

                if (element != null)
                {
                    property.FindPropertyRelative("ID").intValue = element.ID;
                    property.FindPropertyRelative("name").stringValue = element.Name;
                    property.serializedObject.ApplyModifiedProperties();
                    return;
                }
            }
            property.FindPropertyRelative("ID").intValue = 0;
            property.FindPropertyRelative("name").stringValue = string.Empty;
            property.serializedObject.ApplyModifiedProperties();
        }
    }
}